//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<IData.h>
///	@path	~/src/database/
///	@date	2007/11/21
///	@desc	Data entry interface.

#pragma once

#include "xeres.h"

#include "object/IObject.h"
#include "object/IVar.h"

#include "database/database.h"

namespace xeres {

	/*!
		\class	IData
		\brief	Data entry interface.
		\details
			DataEntry is a structure that holds most on disk or in memory data.<BR>
			DataEntry could be a directory, a file,
			or a node(which wrapped an IObject and a serial of attributes).<BR>
			By organizing them in hierarchical order, we can access data in a flexible way.<BR>

		\eg While accessing a shader file, it might looks like:
		\code
				OpenData( "file/shaders/dx9/skin.fx" )
		\endcode

		\eg Also, we can directly refer to the data that inside file:
		\code
				OpenData( "file/etc/options.xml/screen/width" )
		\endcode
	*/
	class IData : public IVar
	{
	public:

		/// \name Constructor & Destructor
		//@{

		/// \ctor
		IData( void );

		/// \dtor
		virtual ~IData( void );

		//@}

		DECL_IOBJECT_INTERFACE( IData , IVar );

	public:

		/// \name Data Accessors
		//@{

		/// \brief Set bool value.
		virtual bool SetBool( bool val );
		/// \brief Set int value.
		virtual bool SetInt( int val );
		/// \brief Set float value.
		virtual bool SetFloat( float val );
		/// \brief Set pair value.
		virtual bool SetPair( const Pair<float>& val );
		/// \brief Set vector value.
		virtual bool SetVector( const Vector<float>& val );
		/// \brief Set quaternion value.
		virtual bool SetQuat( const Quat<float>& val );
		/// \brief Set color value.
		virtual bool SetColor( const Color4& val );
		/// \brief Set matrix value.
		virtual bool SetMatrix( const Matrix<float>& val );
		/// \brief Set string value.
		virtual bool SetString( const WString& val );

		/// \brief Set IObject reference.
		virtual bool SetObject( RefWeak<IObject> val );

		/// \brief Get bool value.
		virtual bool GetBool( bool& val ) const;
		/// \brief Get int value.
		virtual bool GetInt( int& val ) const;
		/// \brief Get float value.
		virtual bool GetFloat( float& val ) const;
		/// \brief Get pair value.
		virtual bool GetPair( Pair<float>& val ) const;
		/// \brief Get vector value.
		virtual bool GetVector( Vector<float>& val ) const;
		/// \brief Get quaternion value.
		virtual bool GetQuat( Quat<float>& val ) const;
		/// \brief Get color value.
		virtual bool GetColor( Color4& val ) const;
		/// \brief Get matrix value.
		virtual bool GetMatrix( Matrix<float>& val ) const;
		/// \brief Get string value.
		virtual bool GetString( WString& val ) const;

		/// \brief Get IObject reference.
		virtual bool GetObject( Ref<IObject>& val ) const;

		/// \brief Read bool value.
		virtual bool ReadBool( const WString& path , bool defaultVal = false );
		/// \brief Read int value.
		virtual int	ReadInt( const WString& path , int defaultVal = 0 );
		/// \brief Read float value.
		virtual float ReadFloat( const WString& path , float defaultVal = 0 );
		/// \brief Read pair value.
		virtual Pair<float> ReadPair( const WString& path , const Pair<float>& defaultVal = Pair<float>(0) );
		/// \brief Read vector value.
		virtual Vector<float> ReadVector( const WString& path , const Vector<float>& defaultVal = Vector<float>(0) );
		/// \brief Read quaternion value.
		virtual Quat<float> ReadQuat( const WString& path , const Quat<float>&defaultVal = Quat<float>(0,0,0,0) );
		/// \brief Read matrix value.
		virtual Matrix<float> ReadMatrix( const WString& path , const Matrix<float>& defaultVal = Matrix<float>() );
		/// \brief Read color value.
		virtual Color4 ReadColor( const WString& path , const Color4& defaultVal = Color4(0,0) );
		/// \brief Read string value.
		virtual WString ReadString( const WString& path , const WString& defaultVal = WString() );

		/// \brief Read binary buffer.
		virtual RefPass<IBuffer> ReadBuffer( const WString& path , RefWeak<IBuffer> defaultVal = RefWeak<IBuffer>(NULL) );

		/// \brief Write bool value.
		virtual bool WriteBool( const WString& path , bool val );
		/// \brief Write int value.
		virtual bool WriteInt( const WString& path , int val );
		/// \brief Write float value.
		virtual bool WriteFloat( const WString& path , float val );
		/// \brief Write pair value.
		virtual bool WritePair( const WString& path , const Pair<float>& val );
		/// \brief Write vector value.
		virtual bool WriteVector( const WString& path , const Vector<float>& val );
		/// \brief Write quaternion value.
		virtual bool WriteQuat( const WString& path , const Quat<float>& val );
		/// \brief Write matrix value.
		virtual bool WriteMatrix( const WString& path , const Matrix<float>& val );
		/// \brief Write color value.
		virtual bool WriteColor( const WString& path , const Color4& val );
		/// \brief Write string value.
		virtual bool WriteString( const WString& path , const WString& val );

		/// \brief Write binary buffer.
		virtual bool WriteBuffer( const WString& path , RefWeak<IBuffer> val );

		/// \brief Read bool array.
		virtual void ReadBools( const WString& path , std::vector<bool>& bools );
		/// \brief Read int array.
		virtual void ReadInts( const WString& path , std::vector<int>& ints );
		/// \brief Read float array.
		virtual void ReadFloats( const WString& path , std::vector<float>& floats );
		/// \brief Read pair array.
		virtual void ReadPairs( const WString& path , std::vector< Pair<float> >& pairs );
		/// \brief Read vector array.
		virtual void ReadVectors( const WString& path , std::vector< Vector<float> >& vectors );
		/// \brief Read quaternion array.
		virtual void ReadQuats( const WString& path , std::vector< Quat<float> >& quats );
		/// \brief Read matrix array.
		virtual void ReadMatrices( const WString& path , std::vector< Matrix<float> >& matrices );
		/// \brief Read color array.
		virtual void ReadColors( const WString& path , std::vector<Color4>& colors );
		/// \brief Read string array.
		virtual void ReadStrings( const WString& path , std::vector<WString>& strings );

		/// \brief Read bool array.
		virtual void ReadBools( const Key& key , std::vector<bool>& bools );
		/// \brief Read int array.
		virtual void ReadInts( const Key& key , std::vector<int>& ints );
		/// \brief Read float array.
		virtual void ReadFloats( const Key& key , std::vector<float>& floats );
		/// \brief Read pair array.
		virtual void ReadPairs( const Key& key , std::vector< Pair<float> >& pairs );
		/// \brief Read vector array.
		virtual void ReadVectors( const Key& key , std::vector< Vector<float> >& vectors );
		/// \brief Read quaternion array.
		virtual void ReadQuats( const Key& key , std::vector< Quat<float> >& quats );
		/// \brief Read matrix array.
		virtual void ReadMatrices( const Key& key , std::vector< Matrix<float> >& matrices );
		/// \brief Read color array.
		virtual void ReadColors( const Key& key , std::vector<Color4>& colors );
		/// \brief Read string array.
		virtual void ReadStrings( const Key& key , std::vector<WString>& strings );

		//@}

		/// \name Data Attributes
		//@{

		/*!
			\brief		Get data info.
		*/
		virtual bool GetInfo( DataInfo& datainfo ) = 0;

		/*!
			\brief		Get data entry key.
		*/
		virtual const Key& GetKey( void ) const = 0;

		/*!
			\brief		Get attribute.
		*/
		virtual bool GetAttribute( const WString& attr , WString& value , const WString& defaultVal = _S("") );

		/*!
			\brief		Set attribute.
		*/
		virtual bool SetAttribute( const WString& attr , const WString& value );

		/*! 
			\brief		Get attribute count.
		*/
		virtual size_t GetAttributeCount( void );

		/*! 
			\brief		Iterate attributes.
		*/
		virtual void * AttributeBegin( void );

		/*! 
			\brief		Get iterator info.
		*/
		virtual bool AttributeIterate( void * context , WString& name , WString& value , bool iterateNext );

		/*! 
			\brief		End iteration.
		*/
		virtual void AttributeEnd( void * context );

		//@}

		/// \name Data Hierarchy
		//@{

		/// \brief Indicates invalid index.
		static const size_t npos = (size_t)(-1);

		/*!
			\brief		Add a child node.
		*/
		virtual bool AddChild( RefWeak<IData> child );

		/*!
			\brief		Create a new entry.
		*/
		virtual RefPass<IData> NewChild( const Key& key );

		/*!
			\brief		Get index of child.
		*/
		virtual bool IndexOf( RefWeak<IData> child , size_t& index );

		/*!
			\brief		Delete child entry.
		*/
		virtual bool DeleteChild( size_t index );

		/*!
			\brief		Delete child entry.
		*/
		virtual bool DeleteChild( RefWeak<IData> child );

		/*!
			\brief		Delete child by key.
		*/
		virtual bool DeleteChild( const Key& key );

		/*!
			\brief		Delete all children.
		*/
		virtual void DeleteChildren( void );

		/*!
			\brief		Delete all children by key.
		*/
		virtual void DeleteChildren( const Key& key );

		/*!
			\brief		Get child entry count.
		*/
		virtual size_t GetChildCount( void );

		/*!
			\brief		Get child entry by key.
		*/
		virtual RefPass<IData> GetChild( const Key& key );

		/*!
			\brief		Get child entry by index.
		*/
		virtual RefPass<IData> GetChild( size_t index );

		/*!
			\brief		Get child entry by name.
		*/
		virtual RefPass<IData> GetChild( const WString& name );

		/*!
			\brief		Get child info by key.
		*/
		virtual bool GetChildInfo( const Key& key , DataInfo& info );

		/*!
			\brief		Get child info by name.
		*/
		virtual bool GetChildInfo( const WString& name , DataInfo& info );

		/*!
			\brief		Get child info by index.
		*/
		virtual bool GetChildInfo( size_t index , DataInfo& info , WString& name );

		/*!
			\brief		Find child by key, based on the index to start, return index and result.
		*/
		virtual bool FindChildIndex( const Key& key , size_t& index );

		/*!
			\brief		Find child by name, based on the index to start, return index and result.
		*/
		virtual bool FindChildIndex( const WString& name , size_t& index );

		/*!
			\brief		Find child by key, and based on index.
		*/
		virtual RefPass<IData> FindChild( const Key& key , size_t& index );

		/*!
			\brief		Find child by name, and based on index.
		*/
		virtual RefPass<IData> FindChild( const WString& name , size_t& index );

		/*!
			\brief		Open an entry based on current entry by path.
		*/
		virtual RefPass<IData> OpenData( const WString& path , bool create_non_exist = false );

		/*!
			\brief		Open an entry based on current entry by path.
		*/
		virtual void OpenDataArray( const WString& path , std::vector< Ref<IData> >& entries );

		/*!
			\brief		Open entry by child sequence (decoded path).
		*/
		RefPass<IData> OpenDataByKeys( const std::vector<Key>& keys , size_t limit = 0 );

		//@}

		/// \name Save & Load
		//@{

		/*!
			\brief		Save data entry to storage.
		*/
		virtual bool Save( void )= 0;

		/*!
			\brief		Reload data entry from storage.
		*/
		virtual bool Reload( void ) = 0;

		//@}

	private:

		/// Inherited from IVar, but disable under IData.
		virtual bool DuplicateFrom( const Ref<IVar>& val );
	};

	// accessing data entry by type
	template<
		typename _Type
	> struct AccessEntry;
	template <> struct AccessEntry <bool> {
		static inline bool Get( RefWeak<IData> entry , bool& value ) { return entry->GetBool(value); }
		static inline bool Set( RefWeak<IData> entry , bool& value ) { return entry->SetBool(value); }
		static inline bool Read( RefWeak<IData> entry , const WString& path ) { return entry->ReadBool(path); }
		static inline bool Write( RefWeak<IData> entry , const WString& path , bool value ) { return entry->WriteBool(path,value); }
		static inline void GetArray( RefWeak<IData> entry , const Key& key , std::vector<bool>& array ) { entry->ReadBools( key , array ); }
		static inline void GetArray( RefWeak<IData> entry , const WString& path , std::vector<bool>& array ) { entry->ReadBools( path , array ); }
	};
	template <> struct AccessEntry <int> {
		static inline bool Get( RefWeak<IData> entry , int& value ) { return entry->GetInt(value); }
		static inline bool Set( RefWeak<IData> entry , int& value ) { return entry->SetInt(value); }
		static inline int Read( RefWeak<IData> entry , const WString& path ) { return entry->ReadInt(path); }
		static inline bool Write( RefWeak<IData> entry , const WString& path , int value ) { return entry->WriteInt(path,value); }
		static inline void GetArray( RefWeak<IData> entry , const Key& key , std::vector<int>& array ) { entry->ReadInts( key , array ); }
		static inline void GetArray( RefWeak<IData> entry , const WString& path , std::vector<int>& array ) { entry->ReadInts( path , array ); }
	};
	template <> struct AccessEntry <float> {
		static inline bool Get( RefWeak<IData> entry , float& value ) { return entry->GetFloat(value); }
		static inline bool Set( RefWeak<IData> entry , float& value ) { return entry->SetFloat(value); }
		static inline float Read( RefWeak<IData> entry , const WString& path ) { return entry->ReadFloat(path); }
		static inline bool Write( RefWeak<IData> entry , const WString& path , float value ) { return entry->WriteFloat(path,value); }
		static inline void GetArray( RefWeak<IData> entry , const Key& key , std::vector<float>& array ) { entry->ReadFloats( key , array ); }
		static inline void GetArray( RefWeak<IData> entry , const WString& path , std::vector<int>& array ) { entry->ReadInts( path , array ); }
	};
	template <> struct AccessEntry < Pair<float> > {
		static inline bool Get( RefWeak<IData> entry , Pair<float>& value ) { return entry->GetPair(value); }
		static inline bool Set( RefWeak<IData> entry , Pair<float>& value ) { return entry->SetPair(value); }
		static inline Pair<float> Read( RefWeak<IData> entry , const WString& path ) { return entry->ReadPair(path); }
		static inline bool Write( RefWeak<IData> entry , const WString& path , const Pair<float>& value ) { return entry->WritePair(path,value); }
		static inline void GetArray( RefWeak<IData> entry , const Key& key , std::vector< Pair<float> >& array ) { entry->ReadPairs( key , array ); }
		static inline void GetArray( RefWeak<IData> entry , const WString& path , std::vector< Pair<float> >& array ) { entry->ReadPairs( path , array ); }
	};
	template <> struct AccessEntry < Vector<float> > {
		static inline bool Get( RefWeak<IData> entry , Vector<float>& value ) { return entry->GetVector(value); }
		static inline bool Set( RefWeak<IData> entry , Vector<float>& value ) { return entry->SetVector(value); }
		static inline Vector<float> Read( RefWeak<IData> entry , const WString& path ) { return entry->ReadVector(path); }
		static inline bool Write( RefWeak<IData> entry , const WString& path , const Vector<float>& value ) { return entry->WriteVector(path,value); }
		static inline void GetArray( RefWeak<IData> entry , const Key& key , std::vector< Vector<float> >& array ) { entry->ReadVectors( key , array ); }
		static inline void GetArray( RefWeak<IData> entry , const WString& path , std::vector< Vector<float> >& array ) { entry->ReadVectors( path , array ); }
	};
	template <> struct AccessEntry < Quat<float> > {
		static inline bool Get( RefWeak<IData> entry , Quat<float>& value ) { return entry->GetQuat(value); }
		static inline bool Set( RefWeak<IData> entry , Quat<float>& value ) { return entry->SetQuat(value); }
		static inline Quat<float> Read( RefWeak<IData> entry , const WString& path ) { return entry->ReadQuat(path); }
		static inline bool Write( RefWeak<IData> entry , const WString& path , const Quat<float>& value ) { return entry->WriteQuat(path,value); }
		static inline void GetArray( RefWeak<IData> entry , const Key& key , std::vector< Quat<float> >& array ) { entry->ReadQuats( key , array ); }
		static inline void GetArray( RefWeak<IData> entry , const WString& path , std::vector< Quat<float> >& array ) { entry->ReadQuats( path , array ); }
	};
	template <> struct AccessEntry < Matrix<float> > {
		static inline bool Get( RefWeak<IData> entry , Matrix<float>& value ) { return entry->GetMatrix(value); }
		static inline bool Set( RefWeak<IData> entry , Matrix<float>& value ) { return entry->SetMatrix(value); }
		static inline Matrix<float> Read( RefWeak<IData> entry , const WString& path ) { return entry->ReadMatrix(path); }
		static inline bool Write( RefWeak<IData> entry , const WString& path , const Matrix<float>& value ) { return entry->WriteMatrix(path,value); }
		static inline void GetArray( RefWeak<IData> entry , const Key& key , std::vector< Matrix<float> >& array ) { entry->ReadMatrices( key , array ); }
		static inline void GetArray( RefWeak<IData> entry , const WString& path , std::vector< Matrix<float> >& array ) { entry->ReadMatrices( path , array ); }
	};
	template <> struct AccessEntry <Color4> {
		static inline bool Get( RefWeak<IData> entry , Color4& value ) { return entry->GetColor(value); }
		static inline bool Set( RefWeak<IData> entry , Color4& value ) { return entry->SetColor(value); }
		static inline Color4 Read( RefWeak<IData> entry , const WString& path ) { return entry->ReadColor(path); }
		static inline bool Write( RefWeak<IData> entry , const WString& path , const Color4 value ) { return entry->WriteColor(path,value); }
		static inline void GetArray( RefWeak<IData> entry , const Key& key , std::vector<Color4>& array ) { entry->ReadColors( key , array ); }
		static inline void GetArray( RefWeak<IData> entry , const WString& path , std::vector<Color4>& array ) { entry->ReadColors( path , array ); }
	};
	template <> struct AccessEntry <WString> {
		static inline bool Get( RefWeak<IData> entry , WString& value ) { return entry->GetString(value); }
		static inline bool Set( RefWeak<IData> entry , WString& value ) { return entry->SetString(value); }
		static inline WString Read( RefWeak<IData> entry , const WString& path ) { return entry->ReadString(path); }
		static inline bool Write( RefWeak<IData> entry , const WString& path , const WString& value ) { return entry->WriteString(path,value); }
		static inline void GetArray( RefWeak<IData> entry , const Key& key , std::vector<WString>& array ) { entry->ReadStrings( key , array ); }
		static inline void GetArray( RefWeak<IData> entry , const WString& path , std::vector<WString>& array ) { entry->ReadStrings( path , array ); }
	};

} // namespace xeres
